package com.dl698.axdr;

import com.dl698.asn1.axdr.AxdrType;
import com.dl698.util.ReverseByteArrayInputStream;
import com.dl698.util.ReverseByteArrayOutputStream;
import com.dl698.asn1.axdr.AxdrNull;
import com.dl698.asn1.axdr.AxdrBoolean;
import com.dl698.asn1.axdr.AxdrBitString;
import com.dl698.asn1.axdr.AxdrOctetString;
import com.dl698.asn1.axdr.AxdrEnum;

import java.io.IOException;

public class Data implements AxdrType {

    public enum Choice {
        _ERR_NONE_SELECTED(-1),
        NULL_DATA(0),
        ARRAY(1),
        STRUCTURE(2),
        BOOL(3),
        BIT_STRING(4),
        DOUBLE_LONG(5),
        DOUBLE_LONG_UNSIGNED(6),
        OCTET_STRING(9),
        VISIBLE_STRING(10),
        UTF8_STRING(12),
        INTEGER(15),
        LONGDATA(16),
        UNSIGNED(17),
        LONG_UNSIGNED(18),
        LONG64(20),
        LONG64_UNSIGNED(21),
        ENUMDATA(22),
        FLOAT32(23),
        FLOAT64(24),
        DATE_TIME(25),
        DATE(26),
        TIME(27),
        DATE_TIME_S(28),
        OI(80),
        OAD(81),
        ROAD(82),
        OMD(83),
        TI(84),
        TSA(85),
        MAC(86),
        RN(87),
        REGION(88),
        SCALER_UNIT(89),
        RSD(90),
        CSD(91),
        MS(92),
        SID(93),
        SID_MAC(94),
        COMDCB(95),
        RCSD(96),
        DONT_CARE(255);

        private final int value;

        Choice(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }

        public static Choice fromValue(int value) {
            for (Choice choice : Choice.values()) {
                if (choice.value == value) {
                    return choice;
                }
            }
            return _ERR_NONE_SELECTED;
        }
    }

    private byte[] dataCode = null;
    private Choice choice = Choice._ERR_NONE_SELECTED;
    // 修改字段类型以匹配实际使用的类
    private AxdrNull null_data = null;
    private AxdrArray array = null;
    private AxdrStructure structure = null;
    private AxdrBoolean bool = null;
    private AxdrBitString bit_string = null;
    private AxdrInteger32 double_long = null;
    private AxdrUnsigned32 double_long_unsigned = null;
    private AxdrOctetString octet_string = null;
    private AxdrVisibleString visible_string = null;
    private AxdrUTF8String utf8_string = null;
    private AxdrInteger8 integer = null;
    private AxdrInteger16 longdata = null;
    private AxdrUnsigned8 unsigned = null;
    private AxdrUnsigned16 long_unsigned = null;
    private AxdrInteger64 long64 = null;
    private AxdrUnsigned64 long64_unsigned = null;
    private AxdrEnum enumdata = null;
    private AxdrFloat32 float32 = null;
    private AxdrFloat64 float64 = null;
    private AxdrDateTime date_time = null;
    private AxdrDate date = null;
    private AxdrTime time = null;
    private AxdrDateTimeS date_time_s = null;
    private OI oi = null;
    private OAD oad = null;
    private ROAD road = null;
    private OMD omd = null;
    private TI ti = null;
    private TSA tsa = null;
    private MAC mac = null;
    private RN rn = null;
    private REGION region = null;
    private SCALER_UNIT scaler_unit = null;
    private RSD rsd = null;
    private CSD csd = null;
    private MS ms = null;
    private SID sid = null;
    private SIDMAC sid_mac = null;
    private COMDCB comdcb = null;
    private RCSD rcsd = null;
    private AxdrNull dont_care = null;

    public Data() {
    }

    public void setDataCode(byte[] dataCode) {
        this.dataCode = dataCode;
    }

    @Override
    public int decode(ReverseByteArrayInputStream input) {
        int codeLength = 0;
        AxdrEnum axdrEnum = new AxdrEnum();
        axdrEnum.setConst();
        try {
            codeLength += axdrEnum.decode(input);
            this.choice = Choice.fromValue((int) axdrEnum.getValue());

            if (this.choice == Choice.NULL_DATA) {
                this.null_data = new NullData();
                codeLength += this.null_data.decode(input);
            } else if (this.choice == Choice.ARRAY) {
                this.array = new AxdrArray();
                codeLength += this.array.decode(input);
            } else if (this.choice == Choice.STRUCTURE) {
                this.structure = new AxdrStructure();
                codeLength += this.structure.decode(input);
            } else if (this.choice == Choice.BOOL) {
                this.bool = new AxdrBoolean();
                codeLength += this.bool.decode(input);
            } else if (this.choice == Choice.BIT_STRING) {
                this.bit_string = new AxdrBitString();
                codeLength += this.bit_string.decode(input);
            } else if (this.choice == Choice.DOUBLE_LONG) {
                this.double_long = new AxdrInteger32();
                codeLength += this.double_long.decode(input);
            } else if (this.choice == Choice.DOUBLE_LONG_UNSIGNED) {
                this.double_long_unsigned = new AxdrUnsigned32();
                codeLength += this.double_long_unsigned.decode(input);
            } else if (this.choice == Choice.OCTET_STRING) {
                this.octet_string = new AxdrOctetString();
                codeLength += this.octet_string.decode(input);
            } else if (this.choice == Choice.VISIBLE_STRING) {
                this.visible_string = new AxdrVisibleString();
                codeLength += this.visible_string.decode(input);
            } else if (this.choice == Choice.UTF8_STRING) {
                this.utf8_string = new AxdrUTF8String();
                codeLength += this.utf8_string.decode(input);
            } else if (this.choice == Choice.INTEGER) {
                this.integer = new AxdrInteger8();
                codeLength += this.integer.decode(input);
            } else if (this.choice == Choice.LONGDATA) {
                this.longdata = new AxdrInteger16();
                codeLength += this.longdata.decode(input);
            } else if (this.choice == Choice.UNSIGNED) {
                this.unsigned = new AxdrUnsigned8();
                codeLength += this.unsigned.decode(input);
            } else if (this.choice == Choice.LONG_UNSIGNED) {
                this.long_unsigned = new AxdrUnsigned16();
                codeLength += this.long_unsigned.decode(input);
            } else if (this.choice == Choice.LONG64) {
                this.long64 = new AxdrInteger64();
                codeLength += this.long64.decode(input);
            } else if (this.choice == Choice.LONG64_UNSIGNED) {
                this.long64_unsigned = new AxdrUnsigned64();
                codeLength += this.long64_unsigned.decode(input);
            } else if (this.choice == Choice.ENUMDATA) {
                this.enumdata = new AxdrEnum();
                this.enumdata.setConst();
                codeLength += this.enumdata.decode(input);
            } else if (this.choice == Choice.FLOAT32) {
                this.float32 = new AxdrFloat32();
                codeLength += this.float32.decode(input);
            } else if (this.choice == Choice.FLOAT64) {
                this.float64 = new AxdrFloat64();
                codeLength += this.float64.decode(input);
            } else if (this.choice == Choice.DATE_TIME) {
                this.date_time = new AxdrDateTime();
                codeLength += this.date_time.decode(input);
            } else if (this.choice == Choice.DATE) {
                this.date = new AxdrDate();
                codeLength += this.date.decode(input);
            } else if (this.choice == Choice.TIME) {
                this.time = new AxdrTime();
                codeLength += this.time.decode(input);
            } else if (this.choice == Choice.DATE_TIME_S) {
                this.date_time_s = new AxdrDateTimeS();
                codeLength += this.date_time_s.decode(input);
            } else if (this.choice == Choice.OI) {
                this.oi = new OI();
                codeLength += this.oi.decode(input);
            } else if (this.choice == Choice.OAD) {
                this.oad = new OAD();
                codeLength += this.oad.decode(input);
            } else if (this.choice == Choice.ROAD) {
                this.road = new ROAD();
                codeLength += this.road.decode(input);
            } else if (this.choice == Choice.OMD) {
                this.omd = new OMD();
                codeLength += this.omd.decode(input);
            } else if (this.choice == Choice.TI) {
                this.ti = new TI();
                codeLength += this.ti.decode(input);
            } else if (this.choice == Choice.TSA) {
                this.tsa = new TSA();
                codeLength += this.tsa.decode(input);
            } else if (this.choice == Choice.MAC) {
                this.mac = new MAC();
                codeLength += this.mac.decode(input);
            } else if (this.choice == Choice.RN) {
                this.rn = new RN();
                codeLength += this.rn.decode(input);
            } else if (this.choice == Choice.REGION) {
                this.region = new REGION();
                codeLength += this.region.decode(input);
            } else if (this.choice == Choice.SCALER_UNIT) {
                this.scaler_unit = new SCALER_UNIT();
                codeLength += this.scaler_unit.decode(input);
            } else if (this.choice == Choice.RSD) {
                this.rsd = new RSD();
                codeLength += this.rsd.decode(input);
            } else if (this.choice == Choice.CSD) {
                this.csd = new CSD();
                codeLength += this.csd.decode(input);
            } else if (this.choice == Choice.MS) {
                this.ms = new MS();
                codeLength += this.ms.decode(input);
            } else if (this.choice == Choice.SID) {
                this.sid = new SID();
                codeLength += this.sid.decode(input);
            } else if (this.choice == Choice.SID_MAC) {
                this.sid_mac = new SIDMAC();
                codeLength += this.sid_mac.decode(input);
            } else if (this.choice == Choice.COMDCB) {
                this.comdcb = new COMDCB();
                codeLength += this.comdcb.decode(input);
            } else if (this.choice == Choice.RCSD) {
                this.rcsd = new RCSD();
                codeLength += this.rcsd.decode(input);
            } else if (this.choice == Choice.DONT_CARE) {
                // DONT_CARE不需要解码额外数据
                this.dont_care = new NullData();
            } else {
                throw new RuntimeException("Unknown choice value: " + axdrEnum.getValue());
            }
        } catch (RuntimeException e) {
            throw new RuntimeException("RuntimeException during decode: " + e.getMessage(), e);
        }

        return codeLength;
    }

    @Override
    public int encode(ReverseByteArrayOutputStream output) {
        int codeLength;

        try {
            if (this.dataCode != null) {
                codeLength = this.dataCode.length;
                for (int i = this.dataCode.length - 1; i >= 0; i--) {
                    output.write(this.dataCode[i]);
                }
            } else {
                AxdrEnum axdrEnum = new AxdrEnum();
                axdrEnum.setMinMaxVal(this.choice.getValue());
                codeLength = axdrEnum.encode(output);

                if (this.choice == Choice.NULL_DATA) {
                    if (this.null_data != null) {
                        codeLength += this.null_data.encode(output);
                    } else {
                        throw new RuntimeException("null_data is null");
                    }
                } else if (this.choice == Choice.ARRAY) {
                    if (this.array != null) {
                        codeLength += this.array.encode(output);
                    } else {
                        throw new RuntimeException("array is null");
                    }
                } else if (this.choice == Choice.STRUCTURE) {
                    if (this.structure != null) {
                        codeLength += this.structure.encode(output);
                    } else {
                        throw new RuntimeException("structure is null");
                    }
                } else if (this.choice == Choice.BOOL) {
                    if (this.bool != null) {
                        codeLength += this.bool.encode(output);
                    } else {
                        throw new RuntimeException("bool is null");
                    }
                } else if (this.choice == Choice.BIT_STRING) {
                    if (this.bit_string != null) {
                        codeLength += this.bit_string.encode(output);
                    } else {
                        throw new RuntimeException("bit_string is null");
                    }
                } else if (this.choice == Choice.DOUBLE_LONG) {
                    if (this.double_long != null) {
                        codeLength += this.double_long.encode(output);
                    } else {
                        throw new RuntimeException("double_long is null");
                    }
                } else if (this.choice == Choice.DOUBLE_LONG_UNSIGNED) {
                    if (this.double_long_unsigned != null) {
                        codeLength += this.double_long_unsigned.encode(output);
                    } else {
                        throw new RuntimeException("double_long_unsigned is null");
                    }
                } else if (this.choice == Choice.OCTET_STRING) {
                    if (this.octet_string != null) {
                        codeLength += this.octet_string.encode(output);
                    } else {
                        throw new RuntimeException("octet_string is null");
                    }
                } else if (this.choice == Choice.VISIBLE_STRING) {
                    if (this.visible_string != null) {
                        codeLength += this.visible_string.encode(output);
                    } else {
                        throw new RuntimeException("visible_string is null");
                    }
                } else if (this.choice == Choice.UTF8_STRING) {
                    if (this.utf8_string != null) {
                        codeLength += this.utf8_string.encode(output);
                    } else {
                        throw new RuntimeException("utf8_string is null");
                    }
                } else if (this.choice == Choice.INTEGER) {
                    if (this.integer != null) {
                        codeLength += this.integer.encode(output);
                    } else {
                        throw new RuntimeException("integer is null");
                    }
                } else if (this.choice == Choice.LONGDATA) {
                    if (this.longdata != null) {
                        codeLength += this.longdata.encode(output);
                    } else {
                        throw new RuntimeException("longdata is null");
                    }
                } else if (this.choice == Choice.UNSIGNED) {
                    if (this.unsigned != null) {
                        codeLength += this.unsigned.encode(output);
                    } else {
                        throw new RuntimeException("unsigned is null");
                    }
                } else if (this.choice == Choice.LONG_UNSIGNED) {
                    if (this.long_unsigned != null) {
                        codeLength += this.long_unsigned.encode(output);
                    } else {
                        throw new RuntimeException("long_unsigned is null");
                    }
                } else if (this.choice == Choice.LONG64) {
                    if (this.long64 != null) {
                        codeLength += this.long64.encode(output);
                    } else {
                        throw new RuntimeException("long64 is null");
                    }
                } else if (this.choice == Choice.LONG64_UNSIGNED) {
                    if (this.long64_unsigned != null) {
                        codeLength += this.long64_unsigned.encode(output);
                    } else {
                        throw new RuntimeException("long64_unsigned is null");
                    }
                } else if (this.choice == Choice.ENUMDATA) {
                    if (this.enumdata != null) {
                        codeLength += this.enumdata.encode(output);
                    } else {
                        throw new RuntimeException("enumdata is null");
                    }
                } else if (this.choice == Choice.FLOAT32) {
                    if (this.float32 != null) {
                        codeLength += this.float32.encode(output);
                    } else {
                        throw new RuntimeException("float32 is null");
                    }
                } else if (this.choice == Choice.FLOAT64) {
                    if (this.float64 != null) {
                        codeLength += this.float64.encode(output);
                    } else {
                        throw new RuntimeException("float64 is null");
                    }
                } else if (this.choice == Choice.DATE_TIME) {
                    if (this.date_time != null) {
                        codeLength += this.date_time.encode(output);
                    } else {
                        throw new RuntimeException("date_time is null");
                    }
                } else if (this.choice == Choice.DATE) {
                    if (this.date != null) {
                        codeLength += this.date.encode(output);
                    } else {
                        throw new RuntimeException("date is null");
                    }
                } else if (this.choice == Choice.TIME) {
                    if (this.time != null) {
                        codeLength += this.time.encode(output);
                    } else {
                        throw new RuntimeException("time is null");
                    }
                } else if (this.choice == Choice.DATE_TIME_S) {
                    if (this.date_time_s != null) {
                        codeLength += this.date_time_s.encode(output);
                    } else {
                        throw new RuntimeException("date_time_s is null");
                    }
                } else if (this.choice == Choice.OI) {
                    if (this.oi != null) {
                        codeLength += this.oi.encode(output);
                    } else {
                        throw new RuntimeException("oi is null");
                    }
                } else if (this.choice == Choice.OAD) {
                    if (this.oad != null) {
                        codeLength += this.oad.encode(output);
                    } else {
                        throw new RuntimeException("oad is null");
                    }
                } else if (this.choice == Choice.ROAD) {
                    if (this.road != null) {
                        codeLength += this.road.encode(output);
                    } else {
                        throw new RuntimeException("road is null");
                    }
                } else if (this.choice == Choice.OMD) {
                    if (this.omd != null) {
                        codeLength += this.omd.encode(output);
                    } else {
                        throw new RuntimeException("omd is null");
                    }
                } else if (this.choice == Choice.TI) {
                    if (this.ti != null) {
                        codeLength += this.ti.encode(output);
                    } else {
                        throw new RuntimeException("ti is null");
                    }
                } else if (this.choice == Choice.TSA) {
                    if (this.tsa != null) {
                        codeLength += this.tsa.encode(output);
                    } else {
                        throw new RuntimeException("tsa is null");
                    }
                } else if (this.choice == Choice.MAC) {
                    if (this.mac != null) {
                        codeLength += this.mac.encode(output);
                    } else {
                        throw new RuntimeException("mac is null");
                    }
                } else if (this.choice == Choice.RN) {
                    if (this.rn != null) {
                        codeLength += this.rn.encode(output);
                    } else {
                        throw new RuntimeException("rn is null");
                    }
                } else if (this.choice == Choice.REGION) {
                    if (this.region != null) {
                        codeLength += this.region.encode(output);
                    } else {
                        throw new RuntimeException("region is null");
                    }
                } else if (this.choice == Choice.SCALER_UNIT) {
                    if (this.scaler_unit != null) {
                        codeLength += this.scaler_unit.encode(output);
                    } else {
                        throw new RuntimeException("scaler_unit is null");
                    }
                } else if (this.choice == Choice.RSD) {
                    if (this.rsd != null) {
                        codeLength += this.rsd.encode(output);
                    } else {
                        throw new RuntimeException("rsd is null");
                    }
                } else if (this.choice == Choice.CSD) {
                    if (this.csd != null) {
                        codeLength += this.csd.encode(output);
                    } else {
                        throw new RuntimeException("csd is null");
                    }
                } else if (this.choice == Choice.MS) {
                    if (this.ms != null) {
                        codeLength += this.ms.encode(output);
                    } else {
                        throw new RuntimeException("ms is null");
                    }
                } else if (this.choice == Choice.SID) {
                    if (this.sid != null) {
                        codeLength += this.sid.encode(output);
                    } else {
                        throw new RuntimeException("sid is null");
                    }
                } else if (this.choice == Choice.SID_MAC) {
                    if (this.sid_mac != null) {
                        codeLength += this.sid_mac.encode(output);
                    } else {
                        throw new RuntimeException("sid_mac is null");
                    }
                } else if (this.choice == Choice.COMDCB) {
                    if (this.comdcb != null) {
                        codeLength += this.comdcb.encode(output);
                    } else {
                        throw new RuntimeException("comdcb is null");
                    }
                } else if (this.choice == Choice.RCSD) {
                    if (this.rcsd != null) {
                        codeLength += this.rcsd.encode(output);
                    } else {
                        throw new RuntimeException("rcsd is null");
                    }
                } else if (this.choice == Choice.DONT_CARE) {
                    if (this.dont_care != null) {
                        codeLength += this.dont_care.encode(output);
                    } else {
                        throw new RuntimeException("dont_care is null");
                    }
                } else {
                    throw new RuntimeException("Unknown choice: " + this.choice);
                }
            }
        } catch (java.io.IOException e) {
            throw new RuntimeException("IOException during encode: " + e.getMessage(), e);
        }
        return codeLength;
    }

    public void encodeAndSave(int encodingSizeGuess) {
        ReverseByteArrayOutputStream revOStream = new ReverseByteArrayOutputStream();
        revOStream.setBufSize(encodingSizeGuess);
        try {
            this.encode(revOStream);
        } catch (Exception e) {
            // Handle exception
        }
        this.dataCode = revOStream.getArray();
    }

    private void resetChoices() {
        this.null_data = null;
        this.array = null;
        this.structure = null;
        this.bool = null;
        this.bit_string = null;
        this.double_long = null;
        this.double_long_unsigned = null;
        this.octet_string = null;
        this.visible_string = null;
        this.utf8_string = null;
        this.integer = null;
        this.longdata = null;
        this.unsigned = null;
        this.long_unsigned = null;
        this.long64 = null;
        this.long64_unsigned = null;
        this.enumdata = null;
        this.float32 = null;
        this.float64 = null;
        this.date_time = null;
        this.date = null;
        this.time = null;
        this.date_time_s = null;
        this.oi = null;
        this.oad = null;
        this.road = null;
        this.omd = null;
        this.ti = null;
        this.tsa = null;
        this.mac = null;
        this.rn = null;
        this.region = null;
        this.scaler_unit = null;
        this.rsd = null;
        this.csd = null;
        this.ms = null;
        this.sid = null;
        this.sid_mac = null;
        this.comdcb = null;
        this.rcsd = null;
        this.dont_care = null;
    }

    // Setter methods
    public void setNullData(AxdrNull null_data) {
        resetChoices();
        this.choice = Choice.NULL_DATA;
        this.null_data = null_data;
    }

    public void setArray(AxdrArray array) {
        resetChoices();
        this.choice = Choice.ARRAY;
        this.array = array;
    }

    public void setStructure(AxdrStructure structure) {
        resetChoices();
        this.choice = Choice.STRUCTURE;
        this.structure = structure;
    }

    public void setBool(AxdrBoolean bool) {
        resetChoices();
        this.choice = Choice.BOOL;
        this.bool = bool;
    }

    public void setBitString(AxdrBitString bit_string) {
        resetChoices();
        this.choice = Choice.BIT_STRING;
        this.bit_string = bit_string;
    }

    public void setDoubleLong(AxdrInteger32 double_long) {
        resetChoices();
        this.choice = Choice.DOUBLE_LONG;
        this.double_long = double_long;
    }

    public void setDoubleLongUnsigned(AxdrUnsigned32 double_long_unsigned) {
        resetChoices();
        this.choice = Choice.DOUBLE_LONG_UNSIGNED;
        this.double_long_unsigned = double_long_unsigned;
    }

    public void setOctetString(AxdrOctetString octet_string) {
        resetChoices();
        this.choice = Choice.OCTET_STRING;
        this.octet_string = octet_string;
    }

    public void setVisibleString(AxdrVisibleString visible_string) {
        resetChoices();
        this.choice = Choice.VISIBLE_STRING;
        this.visible_string = visible_string;
    }

    public void setUtf8String(AxdrUTF8String utf8_string) {
        resetChoices();
        this.choice = Choice.UTF8_STRING;
        this.utf8_string = utf8_string;
    }

    public void setInteger(AxdrInteger8 integer) {
        resetChoices();
        this.choice = Choice.INTEGER;
        this.integer = integer;
    }

    public void setLongData(AxdrInteger16 longdata) {
        resetChoices();
        this.choice = Choice.LONGDATA;
        this.longdata = longdata;
    }

    public void setUnsigned(AxdrUnsigned8 unsigned) {
        resetChoices();
        this.choice = Choice.UNSIGNED;
        this.unsigned = unsigned;
    }

    public void setLongUnsigned(AxdrUnsigned16 long_unsigned) {
        resetChoices();
        this.choice = Choice.LONG_UNSIGNED;
        this.long_unsigned = long_unsigned;
    }

    public void setLong64(AxdrInteger64 long64) {
        resetChoices();
        this.choice = Choice.LONG64;
        this.long64 = long64;
    }

    public void setLong64Unsigned(AxdrUnsigned64 long64_unsigned) {
        resetChoices();
        this.choice = Choice.LONG64_UNSIGNED;
        this.long64_unsigned = long64_unsigned;
    }

    public void setEnumData(AxdrEnum enumdata) {
        resetChoices();
        this.choice = Choice.ENUMDATA;
        this.enumdata = enumdata;
    }

    public void setFloat32(AxdrFloat32 float32) {
        resetChoices();
        this.choice = Choice.FLOAT32;
        this.float32 = float32;
    }

    public void setFloat64(AxdrFloat64 float64) {
        resetChoices();
        this.choice = Choice.FLOAT64;
        this.float64 = float64;
    }

    public void setDateTime(AxdrDateTime date_time) {
        resetChoices();
        this.choice = Choice.DATE_TIME;
        this.date_time = date_time;
    }

    public void setDate(AxdrDate date) {
        resetChoices();
        this.choice = Choice.DATE;
        this.date = date;
    }

    public void setTime(AxdrTime time) {
        resetChoices();
        this.choice = Choice.TIME;
        this.time = time;
    }

    public void setDateTimeS(AxdrDateTimeS date_time_s) {
        resetChoices();
        this.choice = Choice.DATE_TIME_S;
        this.date_time_s = date_time_s;
    }

    public void setOi(OI oi) {
        resetChoices();
        this.choice = Choice.OI;
        this.oi = oi;
    }

    public void setOad(OAD oad) {
        resetChoices();
        this.choice = Choice.OAD;
        this.oad = oad;
    }

    public void setRoad(ROAD road) {
        resetChoices();
        this.choice = Choice.ROAD;
        this.road = road;
    }

    public void setOmd(OMD omd) {
        resetChoices();
        this.choice = Choice.OMD;
        this.omd = omd;
    }

    public void setTi(TI ti) {
        resetChoices();
        this.choice = Choice.TI;
        this.ti = ti;
    }

    public void setTsa(TSA tsa) {
        resetChoices();
        this.choice = Choice.TSA;
        this.tsa = tsa;
    }

    public void setMac(MAC mac) {
        resetChoices();
        this.choice = Choice.MAC;
        this.mac = mac;
    }

    public void setRn(RN rn) {
        resetChoices();
        this.choice = Choice.RN;
        this.rn = rn;
    }

    public void setRegion(REGION region) {
        resetChoices();
        this.choice = Choice.REGION;
        this.region = region;
    }

    public void setScalerUnit(SCALER_UNIT scaler_unit) {
        resetChoices();
        this.choice = Choice.SCALER_UNIT;
        this.scaler_unit = scaler_unit;
    }

    public void setRsd(RSD rsd) {
        resetChoices();
        this.choice = Choice.RSD;
        this.rsd = rsd;
    }

    public void setCsd(CSD csd) {
        resetChoices();
        this.choice = Choice.CSD;
        this.csd = csd;
    }

    public void setMs(MS ms) {
        resetChoices();
        this.choice = Choice.MS;
        this.ms = ms;
    }

    public void setSid(SID sid) {
        resetChoices();
        this.choice = Choice.SID;
        this.sid = sid;
    }

    public void setSidMac(SIDMAC sid_mac) {
        resetChoices();
        this.choice = Choice.SID_MAC;
        this.sid_mac = sid_mac;
    }

    public void setComdcb(COMDCB comdcb) {
        resetChoices();
        this.choice = Choice.COMDCB;
        this.comdcb = comdcb;
    }

    public void setRcsd(RCSD rcsd) {
        resetChoices();
        this.choice = Choice.RCSD;
        this.rcsd = rcsd;
    }

    public void setDontCare(AxdrNull dont_care) {
        resetChoices();
        this.choice = Choice.DONT_CARE;
        this.dont_care = dont_care;
    }

    @Override
    public String toString() {
        if (this.choice == Choice.NULL_DATA) {
            if (this.null_data != null) {
                return "choice: {null_data: " + this.null_data + "}";
            } else {
                return "choice is null_data but null_data is null";
            }
        } else if (this.choice == Choice.ARRAY) {
            if (this.array != null) {
                return "choice: {array: " + this.array + "}";
            } else {
                return "choice is array but array is null";
            }
        } else if (this.choice == Choice.STRUCTURE) {
            if (this.structure != null) {
                return "choice: {structure: " + this.structure + "}";
            } else {
                return "choice is structure but structure is null";
            }
        } else if (this.choice == Choice.BOOL) {
            if (this.bool != null) {
                return "choice: {bool: " + this.bool + "}";
            } else {
                return "choice is bool but bool is null";
            }
        } else if (this.choice == Choice.BIT_STRING) {
            if (this.bit_string != null) {
                return "choice: {bit_string: " + this.bit_string + "}";
            } else {
                return "choice is bit_string but bit_string is null";
            }
        } else if (this.choice == Choice.DOUBLE_LONG) {
            if (this.double_long != null) {
                return "choice: {double_long: " + this.double_long + "}";
            } else {
                return "choice is double_long but double_long is null";
            }
        } else if (this.choice == Choice.DOUBLE_LONG_UNSIGNED) {
            if (this.double_long_unsigned != null) {
                return "choice: {double_long_unsigned: " + this.double_long_unsigned + "}";
            } else {
                return "choice is double_long_unsigned but double_long_unsigned is null";
            }
        } else if (this.choice == Choice.OCTET_STRING) {
            if (this.octet_string != null) {
                return "choice: {octet_string: " + this.octet_string + "}";
            } else {
                return "choice is octet_string but octet_string is null";
            }
        } else if (this.choice == Choice.VISIBLE_STRING) {
            if (this.visible_string != null) {
                return "choice: {visible_string: " + this.visible_string + "}";
            } else {
                return "choice is visible_string but visible_string is null";
            }
        } else if (this.choice == Choice.UTF8_STRING) {
            if (this.utf8_string != null) {
                return "choice: {utf8_string: " + this.utf8_string + "}";
            } else {
                return "choice is utf8_string but utf8_string is null";
            }
        } else if (this.choice == Choice.INTEGER) {
            if (this.integer != null) {
                return "choice: {integer: " + this.integer + "}";
            } else {
                return "choice is integer but integer is null";
            }
        } else if (this.choice == Choice.LONGDATA) {
            if (this.longdata != null) {
                return "choice: {longdata: " + this.longdata + "}";
            } else {
                return "choice is longdata but longdata is null";
            }
        } else if (this.choice == Choice.UNSIGNED) {
            if (this.unsigned != null) {
                return "choice: {unsigned: " + this.unsigned + "}";
            } else {
                return "choice is unsigned but unsigned is null";
            }
        } else if (this.choice == Choice.LONG_UNSIGNED) {
            if (this.long_unsigned != null) {
                return "choice: {long_unsigned: " + this.long_unsigned + "}";
            } else {
                return "choice is long_unsigned but long_unsigned is null";
            }
        } else if (this.choice == Choice.LONG64) {
            if (this.long64 != null) {
                return "choice: {long64: " + this.long64 + "}";
            } else {
                return "choice is long64 but long64 is null";
            }
        } else if (this.choice == Choice.LONG64_UNSIGNED) {
            if (this.long64_unsigned != null) {
                return "choice: {long64_unsigned: " + this.long64_unsigned + "}";
            } else {
                return "choice is long64_unsigned but long64_unsigned is null";
            }
        } else if (this.choice == Choice.ENUMDATA) {
            if (this.enumdata != null) {
                return "choice: {enumdata: " + this.enumdata + "}";
            } else {
                return "choice is enumdata but enumdata is null";
            }
        } else if (this.choice == Choice.FLOAT32) {
            if (this.float32 != null) {
                return "choice: {float32: " + this.float32 + "}";
            } else {
                return "choice is float32 but float32 is null";
            }
        } else if (this.choice == Choice.FLOAT64) {
            if (this.float64 != null) {
                return "choice: {float64: " + this.float64 + "}";
            } else {
                return "choice is float64 but float64 is null";
            }
        } else if (this.choice == Choice.DATE_TIME) {
            if (this.date_time != null) {
                return "choice: {date_time: " + this.date_time + "}";
            } else {
                return "choice is date_time but date_time is null";
            }
        } else if (this.choice == Choice.DATE) {
            if (this.date != null) {
                return "choice: {date: " + this.date + "}";
            } else {
                return "choice is date but date is null";
            }
        } else if (this.choice == Choice.TIME) {
            if (this.time != null) {
                return "choice: {time: " + this.time + "}";
            } else {
                return "choice is time but time is null";
            }
        } else if (this.choice == Choice.DATE_TIME_S) {
            if (this.date_time_s != null) {
                return "choice: {date_time_s: " + this.date_time_s + "}";
            } else {
                return "choice is date_time_s but date_time_s is null";
            }
        } else if (this.choice == Choice.OI) {
            if (this.oi != null) {
                return "choice: {oi: " + this.oi + "}";
            } else {
                return "choice is oi but oi is null";
            }
        } else if (this.choice == Choice.OAD) {
            if (this.oad != null) {
                return "choice: {oad: " + this.oad + "}";
            } else {
                return "choice is oad but oad is null";
            }
        } else if (this.choice == Choice.ROAD) {
            if (this.road != null) {
                return "choice: {road: " + this.road + "}";
            } else {
                return "choice is road but road is null";
            }
        } else if (this.choice == Choice.OMD) {
            if (this.omd != null) {
                return "choice: {omd: " + this.omd + "}";
            } else {
                return "choice is omd but omd null";
            }
        } else if (this.choice == Choice.TI) {
            if (this.ti != null) {
                return "choice: {ti: " + this.ti + "}";
            } else {
                return "choice is ti but oi null";
            }
        } else if (this.choice == Choice.TSA) {
            if (this.tsa != null) {
                return "choice: {tsa: " + this.tsa + "}";
            } else {
                return "choice is tsa but tsa null";
            }
        } else if (this.choice == Choice.MAC) {
            if (this.mac != null) {
                return "choice: {mac: " + this.mac + "}";
            } else {
                return "choice is mac but mac  null";
            }
        } else if (this.choice == Choice.RN) {
            if (this.rn != null) {
                return "choice: {rn: " + this.rn + "}";
            } else {
                return "choice is rn but rn null";
            }
        } else if (this.choice == Choice.REGION) {
            if (this.region != null) {
                return "choice: {region: " + this.region + "}";
            } else {
                return "choice is region but region null";
            }
        } else if (this.choice == Choice.SCALER_UNIT) {
            if (this.scaler_unit != null) {
                return "choice: {scaler_unit: " + this.scaler_unit + "}";
            } else {
                return "choice is scaler_unit but scaler_unit null";
            }
        } else if (this.choice == Choice.RSD) {
            if (this.rsd != null) {
                return "choice: {rsd: " + this.rsd + "}";
            } else {
                return "choice is rsd but rsd null";
            }
        } else if (this.choice == Choice.CSD) {
            if (this.csd != null) {
                return "choice: {csd: " + this.csd + "}";
            } else {
                return "choice is csd but csd null";
            }
        } else if (this.choice == Choice.MS) {
            if (this.ms != null) {
                return "choice: {ms: " + this.ms + "}";
            } else {
                return "choice is ms but ms null";
            }
        } else if (this.choice == Choice.SID) {
            if (this.sid != null) {
                return "choice: {sid: " + this.sid + "}";
            } else {
                return "choice is sid but sid null";
            }
        } else if (this.choice == Choice.SID_MAC) {
            if (this.sid_mac != null) {
                return "choice: {sid_mac: " + this.sid_mac + "}";
            } else {
                return "choice is sid_mac but sid_mac null";
            }
        } else if (this.choice == Choice.COMDCB) {
            if (this.comdcb != null) {
                return "choice: {comdcb: " + this.comdcb + "}";
            } else {
                return "choice is comdcb but comdcb null";
            }
        } else if (this.choice == Choice.RCSD) {
            if (this.rcsd != null) {
                return "choice: {rcsd: " + this.rcsd + "}";
            } else {
                return "choice is rcsd but rcsd null";
            }
        } else if (this.choice == Choice.DONT_CARE) {
            if (this.dont_care != null) {
                return "choice: {dont_care: " + this.dont_care + "}";
            } else {
                return "choice is dont_care but dont_care null";
            }
        } else {
            return "unknown";
        }
    }

    // Getter methods
    public Choice getChoice() {
        return choice;
    }

    public AxdrNull getNullData() {
        return null_data;
    }

    public AxdrArray getArray() {
        return array;
    }

    public AxdrStructure getStructure() {
        return structure;
    }

    public AxdrBoolean getBool() {
        return bool;
    }

    public AxdrBitString getBitString() {
        return bit_string;
    }

    public AxdrInteger32 getDoubleLong() {
        return double_long;
    }

    public AxdrUnsigned32 getDoubleLongUnsigned() {
        return double_long_unsigned;
    }

    public AxdrOctetString getOctetString() {
        return octet_string;
    }

    public AxdrVisibleString getVisibleString() {
        return visible_string;
    }

    public AxdrUTF8String getUtf8String() {
        return utf8_string;
    }

    public AxdrInteger8 getInteger() {
        return integer;
    }

    public AxdrInteger16 getLongData() {
        return longdata;
    }

    public AxdrUnsigned8 getUnsigned() {
        return unsigned;
    }

    public AxdrUnsigned16 getLongUnsigned() {
        return long_unsigned;
    }

    public AxdrInteger64 getLong64() {
        return long64;
    }

    public AxdrUnsigned64 getLong64Unsigned() {
        return long64_unsigned;
    }

    public AxdrEnum getEnumData() {
        return enumdata;
    }

    public AxdrFloat32 getFloat32() {
        return float32;
    }

    public AxdrFloat64 getFloat64() {
        return float64;
    }

    public AxdrDateTime getDateTime() {
        return date_time;
    }

    public AxdrDate getDate() {
        return date;
    }

    public AxdrTime getTime() {
        return time;
    }

    public AxdrDateTimeS getDateTimeS() {
        return date_time_s;
    }

    public OI getOi() {
        return oi;
    }

    public OAD getOad() {
        return oad;
    }

    public ROAD getRoad() {
        return road;
    }

    public OMD getOmd() {
        return omd;
    }

    public TI getTi() {
        return ti;
    }

    public TSA getTsa() {
        return tsa;
    }

    public MAC getMac() {
        return mac;
    }

    public RN getRn() {
        return rn;
    }

    public REGION getRegion() {
        return region;
    }

    public SCALER_UNIT getScalerUnit() {
        return scaler_unit;
    }

    public RSD getRsd() {
        return rsd;
    }

    public CSD getCsd() {
        return csd;
    }

    public MS getMs() {
        return ms;
    }

    public SID getSid() {
        return sid;
    }

    public SIDMAC getSidMac() {
        return sid_mac;
    }

    public COMDCB getComdcb() {
        return comdcb;
    }

    public RCSD getRcsd() {
        return rcsd;
    }

    public AxdrNull getDontCare() {
        return dont_care;
    }
}